perm filename ALKERN.POX[HAL,HE]1 blob
sn#185825 filedate 1975-11-12 generic text, type C, neo UTF8
COMMENT ā VALID 00002 PAGES
C REC PAGE DESCRIPTION
C00001 00001
C00002 00002 \F1\CTHE KERNEL
C00014 ENDMK
Cā;
\F1\CTHE KERNEL
\F0\JThe kernel resides in low core (0 to 13777) of the PDP11 (here after
called the ELF). When it is started at location 1000, it finds the
user's starting address at 13776 and a pointer to his processor
control block at 13777. When the AL system is the "user", it is the
interpreter initialization code that is pointed to by these words.
Control is passed to the user (in cpu user mode).\.
\JProcesses communicate with the kernel by means of the EMT (emulator
trap) instruction. Mechanisms are provided to control multiple
processes, including scheduling in a time-slice environment,
assignment of priorities, an event mechanism with signal and wait
primitives. All system calls pop their arguments off the User stack
and push their return values if they have any. They mostly return
with the C condition code bit zero. An error condition causes a
return with C=1; in that case, the arguments have been popped and no
return values pushed.\.
\JThe basic time quantum in the kernel is currently 2 milliseconds,
although it will eventually be run at 1 millisecond. Processes
can request to sleep for a number of quanta. At the start of each
quantum, all processes which are scheduled for execution are readied,
and those with higher priority have precedence. Any unused time
is soaked up by the null job.\.
\JLevel 7 is the highest priority. This level is only used for
critical operations such as reading the analog-to-digital converter
(ADC) and servoing device joints. Only one level 7 process can be
scheduled for any given time slot. When the Kernel starts a level 7
job running, it interprets the contents of User registers 3 and 4 in
the PDB (Process Descriptor Block)
as pointers to two data arrays. R3 points at a list of ADC
channel numbers (one per word) terminated by a negative number. The
startup routine reads all the channels specified in the array and
puts the results into the corresponding locations in the array that
R4 points at. When the user process gets control, R3 and R4 point at
the first words of the two arrays and all of the channels have been
read. The recommended way for a level 7 job to reschedule itself is
to do a SCHED7 to its own PDB, take note of the returned actual time
interval, and then DISMIS (details below). This procedure minimizes
overhead by not saving and restoring the registers. NOTE: Since
level 7 can not be interrupted (even by floating-point traps), I
don't bother to allocate PDB space for any of the floating-point
stuff.\.
A description of each of the system calls follows.
DISMIS (no arguments)
\JKills the process that uses it. It saves the PC, PSW, and SP but nothing else.
If the process is restarted (as in the level 7 SCHED7-DISMIS sequence) it will
resume after the DISMIS with the stack in the right state but all registers
clobbered. R3 through R5 will be reloaded with what they had at the first
startup.\.
FORK PDB,LOC,PRI
\JStarts up a new process immediately. PDB points at
a process descriptor, LOC is the starting address, and PRI is the
priority of the new process. If PRI is higher than that of the
calling process the new one will run immediately and pre-empt the
caller. FORKing with PRI=7 will work but is not a good idea since
if you do it too late in a clock period the clock might miss a tick.\.
SCHEDU PDB,LOC,PRI,TIME
\JWorks just like FORK except that instead
of starting the target process immediately it puts the process on
the clock queue to start up (TIME) milliseconds from now. This will
also work if PRI=7, but if another level 7 process is already scheduled
for that slot the new one will be put into the queue in the first
available slot after the one you requested.\.
SCHED7 ARRAY,TIME
\JIs a special variation on SCHEDU to allow scheduling
a whole bunch of priority 7 jobs at one whack. ARRAY points at (what
else) which consists of a pointer to a PDB, a return value, another
PDB pointer, another return value, etc., ending with a zero where the
next PDB pointer should be. TIME is the number of milliseconds from
now that the first process should start up. SCHED7 puts the processes
into consecutive time slots if it can. If a slot is already filled,
it uses the next available one. In any case, it returns for each
process the number of number of milliseconds from now that it wound
up being scheduled.\.
SLEEP TIME
\JPuts the requesting process to sleep for (TIME) milliseconds.
If TIME=0, this merely reschedules you for the present time slot.
If your priority is 7 and the time you requested is taken, you will
be scheduled in the first later available slot.\.
EVMAK (no args)
\JCreates an event with its associated counter and
empty queue of jobs waiting. It returns a unique identifier which
you can use later to refer to the event. Events come in two flavors:
the kind you create with this operation, and "permanent" ones that
reflect hardware conditions. Permanent events are identified by
small integers. I'll add their descriptions and identifiers as I
add the events.\.
EVKIL <event id>
\JDestroys the event if it was one that you created,
waking up any processes that are waiting and giving them the C=1
return. If the id doesn't point at an event, or points to a permanent
event, EVKIL does nothing and gives the error return.\.
EVSIG <event id>
\JSignals the event. If any processes are waiting, the
first one will wake up. EVSIG of a permanent event does nothing but
give the error return.\.
EVWAIT <event id>
\JTests the event (of either type) and makes the normal
return if it has happened. If it hasn't happened, your process goes
to sleep waiting for it and gets the normal return when it does happen.
If it is not an event, or it has been EVKILled while you were waiting,
you get the error return. The queue of jobs waiting on an event is
ordered by their nominal priorities, first come first served within
priority levels.\.
EVTST <event id>
\JTests the event and returns normally if it has happened.
If it hasn't, or if it's a non-event, you get the error return with no
waiting.\.
SETPRI PRI
\JSets your priority to PRI or the priority you were originally
run at, whichever is higher, and returns your old priority on the stack.
If you attempted to set your priority below the original, it returns C=1.\.
GETTIM (no args)
\JReturns on your stack the time in milliseconds since the Kernel was last
initialized. The result is a two-word integer in the right format for
a LDCLF or LDCLD instruction.\.